//standard
#include <vector>
#include <string>
#include <iostream>
#include <fstream>

//boost
#include <boost/foreach.hpp>


// components
#include <ultoa.h>
#include <tree.h>
#include <stlhelper.h>
#define DEBUG_LEVEL 6
#include <debug_func.h>
#include <tree_ops.h>
#include <print_error.h>

#include "get_arg.h"

using std::vector;
using std::string;
using std::cout;
using std::cin;
using std::cerr;
using std::istream;
using namespace bcpp_tree_ops;
using namespace bcpp_tree;
using bcpp_tree_ops::op_tree_names_to_short_names;




//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

//	main

//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
int main (int argc, char *argv[])
{

	debug_func_cerr(5);
	t_program_args args;

	try
	{

	// we use cout to print progress so flush per call
	cout.setf(std::ios_base::unitbuf);

	std::ios::sync_with_stdio(false);

	if (!process_command_line_options(argc, argv, args))
		return 1;


//    char buff[4096];
//    cin.rdbuf()->pubsetbuf(buff, 32768); // enable buffering

	std::ofstream ofs(args.name_mapping_file.c_str());
	if (!ofs)
		throw std::runtime_error("Could not open " + args.name_mapping_file);

	unsigned name_index = 0;
	unsigned line_cnt = 1;
	while (cin && !cin.eof())
	{
		//
		//	read tree from cin
		//
		args.VERBOSE() << "\tReading tree...\n";
		bcpp_tree::t_tree tree;

		cin >> t_tree_io_wrapper(tree, line_cnt);

		//
		//	If failed, print no more trees
		//
		if (cin.fail())
			break;

		args.VERBOSE() << "\tConverting names to short forms"
						<< (tree.get_name().length() ? (" for " + tree.get_name()) : "")
						<< " starting with the index of "
						<< name_index << "...\n";
		op_tree_names_to_short_names convert(tree, name_index);
		convert.run();


		typedef std::pair<const string,  string> t_str_pair;
		BOOST_FOREACH( t_str_pair& strings, convert.long_name_to_short_name)
		{
			ofs << strings.second << "\t" << strings.first << "\n";
		}
		args.VERBOSE()	<<"\t"
						<< convert.long_name_to_short_name.size()
						<< " leaf names converted.\n";




		//
		// 	print out tree
		//
		args.VERBOSE() << "\tWriting out converted tree"
						<< (tree.get_name().length() ? (" for " + tree.get_name()) : "")
						<< "\n";

		if (!args.header)
		{
			args.VERBOSE()	<<"\tNo header\n";
			tree.set_name("");
		}

		// If not first tree, print new line separator.
		// then print out tree
		if  (name_index)
			cout << "\n";
		cout << tree;
		name_index += convert.long_name_to_short_name.size();
	}

	args.VERBOSE() << "\tFinished.\n";
	}
	catch (std::exception& e)
	{
		std_print_error(args.CERR(),  e.what());
		return 1;
	}

	return 0;
}



